
import { _decorator, Component, Node, instantiate, Prefab, randomRange, Vec2, Vec3, Label, math, director, resources, find, game, isDisplayStats } from 'cc';
import { Bullet } from './Bullet';
import { Chest } from './Chest';
import { Enemy } from './Enemy';
import { EnemyConfig } from './EnemyConfig';
import { EquitmentManager } from './EquitmentManager';
import { EventManager } from './EventManager';
import { EventType } from './EventType';
import { Exp } from './Exp';
import { JoyStick } from './JoyStick';
import { PlayerController } from './PlayerController';
import { PlayerProp } from './PropType';
import { UIConfig } from './UI/UIConfig';
import { UIManager } from './UIManager';
const { ccclass, property } = _decorator;


@ccclass('GameManager')
export class GameManager extends Component
{
    public static instance: GameManager

    public ExpCount: number // 经验值
    public LvUpExp: number // 升级所需经验值
    public Lv: number // 等级
    public PlayerHP:number
    public PlayerMaxHP:number

    public CurLevel:number = 1 // 当前关卡

    ///////////////// 全局变量 //////////////////////

    public static ENEMY_SPAWN_INTERVEL: number = 2 // 怪物生成间隔(秒)
    public static TURN_TIME: number = 30 // 每回合游戏时长 测试模式




    ////////////////////////////////////////////////
    ///////////////// 敌人相关 //////////////////////
    public EnemytPrefab: Prefab
    @property(Node)
    public EnemyRoot: Node
    public EnemyList: Node[]
    private lastEnemyCreateTime: number = 0
    private EIDIter: number = 1
    ////////////////////////////////////////////////

    @property(Node)
    public Player: Node
    public PlayerController:PlayerController

    public Border:Node

    ///////////////// 经验相关 //////////////////////
    public ExpPrefab: Prefab
    @property(Node)
    public ExpRoot: Node
    public ExpList: Node[]
    ////////////////////////////////////////////////
    ///////////////// 宝箱相关 //////////////////////
    public ChestPrefab: Prefab
    @property(Node)
    public ChestRoot: Node
    public ChestList: Node[] // 地图上的宝箱节点
    public ChestLootCount: number = 0 // 本回合拾取的宝箱数量 测试模式
    ////////////////////////////////////////////////

    private curTimer:number = 0

    public IsGameStart = false
    public IsGamePause = 0
    onLoad()
    {
        GameManager.instance = this
        director.addPersistRootNode(this.node)
        
        resources.load("Prefabs/Enemy", Prefab, (err, prefab) => {
            this.EnemytPrefab = prefab
        });
        resources.load("Prefabs/Chest", Prefab, (err, prefab) => {
            this.ChestPrefab = prefab
        });
        resources.load("Prefabs/Exp", Prefab, (err, prefab) => {
            this.ExpPrefab = prefab
        });
    }

    start()
    {
    }

    update(deltaTime: number)
    {
        if (this.IsGameStart && !(this.IsGamePause > 0))
        {
            this.lastEnemyCreateTime += deltaTime
            if (this.lastEnemyCreateTime > GameManager.ENEMY_SPAWN_INTERVEL)
            {
                this.lastEnemyCreateTime = 0
                this.EnemyList.push(this.CreateEnemy())
            }

            this.UpdateCheckExp()
            this.UpdateCheckChest()

        }

    }

    CreateEnemy()
    {
        let x = randomRange(-1, 1)
        let y = randomRange(-1, 1)
        let rPos = new Vec2(x, y).normalize()
        Vec2.multiplyScalar(rPos, rPos, UIManager.instance.GetCanvasSize().x / 2)
        let config = new EnemyConfig()
        config.Target = this.Player
        config.nMoveSpeed = 3
        config.v2InitPos = rPos
        config.MaxHP = 2
        config.EID = this.EIDIter + 1
        this.EIDIter++
        let enemy = instantiate(this.EnemytPrefab)
        enemy.getComponent(Enemy).Config = config
        enemy.parent = this.EnemyRoot
        return enemy
    }

    //检测子弹是否能击中敌人
    CheckHit(pos: Vec3)
    {
        let ePos = new Vec3()
        let hitE = new Node()
        for (let index = 0; index < this.EnemyList.length; index++)
        {
            const element = this.EnemyList[index];
            ePos = element.getPosition()
            if (Vec3.subtract(ePos, ePos, pos).lengthSqr() < (55 * 55))
            { // 25+30
                hitE = element
                //this.EnemyList.splice(index,1)
                return hitE // 被射中的对象
            }
        }
    }

    // 移除敌人
    // todo 这个遍历可能有性能问题，感觉可以优化一下
    RemoveEnemy(EID: number)
    {
        for (let index = 0; index < this.EnemyList.length; index++)
        {
            if (this.EnemyList[index].getComponent(Enemy).Config.EID == EID)
            {
                this.EnemyList.splice(index, 1)
                return
            }
        }
    }

    //#region 关卡间清场
    ClearAllThing()
    {
        console.log("[GameManager] 清场")
        this.DestroyAllEnemy()
        this.DestroyAllExp()
        this.DestroyAllChest()
    }

    DestroyAllEnemy()
    {
        for (let index = 0; index < this.EnemyList.length; index++)
        {
            this.EnemyList[index].getComponent(Enemy).Kill()
        }
    }

    DestroyAllExp()
    {
        for (let index = 0; index < this.ExpList.length; index++)
        {
            let e = this.ExpList[index]
            e.destroy()
        }
    }

    DestroyAllChest()
    {
        for (let index = 0; index < this.ChestList.length; index++)
        {
            let e = this.ChestList[index]
            e.destroy()
        }
    }
    //#endregion

    CreateExp(pos: Vec3)
    {
        let exp = instantiate(this.ExpPrefab)
        let s = exp.getComponent(Exp)
        s.CurPos = pos
        s.ExpCount = 1
        s.Player = this.Player
        exp.parent = this.ExpRoot
        this.ExpList.push(exp)
        return exp
    }

    CreateChest(pos: Vec3)
    {
        let chest = instantiate(this.ChestPrefab)
        let s = chest.getComponent(Chest)
        s.CurPos = pos
        chest.parent = this.ChestRoot
        this.ChestList.push(chest)
        return chest
    }

    //检测是否碰到经验
    UpdateCheckExp()
    {
        for (let index = 0; index < this.ExpList.length; index++)
        {
            const expPos = this.ExpList[index].getPosition();
            const playerPos = this.Player.getPosition()
            let dis = new Vec3()
            Vec3.subtract(dis, expPos, playerPos)
            if (dis.lengthSqr() < (30 * 30))
            {
                let ec = this.ExpList[index].getComponent(Exp).ExpCount
                this.AddExpCount(ec)
                this.ExpList[index].destroy()
                this.ExpList.splice(index, 1)
            }
        }
    }

    // 检测释放碰到箱子
    UpdateCheckChest()
    {
        for (let index = 0; index < this.ChestList.length; index++)
        {
            const chestPos = this.ChestList[index].getPosition();
            const playerPos = this.Player.getPosition()
            let dis = new Vec3()
            Vec3.subtract(dis, chestPos, playerPos)
            if (dis.lengthSqr() < (30 * 30))
            {
                this.ChestLootCount ++
                this.ChestList[index].destroy()
                this.ChestList.splice(index, 1)
                // let equits = EquitmentManager.instance.RandomEquitment()
                console.log("[GameManager] 捡到箱子！")
                this.IsGamePause ++
                UIManager.instance.OpenUI(UIConfig.OpenChest)
            }
        }
    }

    AddExpCount(ec: number)
    {
        this.ExpCount += ec
        if (this.ExpCount >= this.LvUpExp)
        {
            this.ExpCount = 0
            this.Lv += 1
            this.LvUpExp = (this.Lv + 1) * 5
            this.OnLvUp()
            EventManager.instance.DispatchEvent(EventType.LvUP, this.Lv)
            console.log("[GameManager] 等级提升! ", this.Lv)
        }
        EventManager.instance.DispatchEvent(EventType.ExpChange, this.ExpCount, this.LvUpExp, this.Lv)
    }

    TimeOut()
    {
        if (!this.IsGameStart) {
            return 
        }
        this.IsGameStart = false
        console.log("箱子数量：",this.ChestLootCount)
        if (this.ChestLootCount > 0) {
            UIManager.instance.OpenUI(UIConfig.OpenChest)
        }
        else
        {
            UIManager.instance.OpenUI(UIConfig.Result)
        }
        this.ClearAllThing()
    }

    /* todo
    1.超过一定距离的敌人不做相应，即不会自动攻击超过一定距离的敌人
    2.按照级别更新敌人状态
    3.按照距离设置多级敌人数组
    */ 
    GetClosestEnemy()
    {
        let pPos = this.Player.getPosition()
        let minDis = Number.MAX_VALUE
        let minIndex = -1
        for (let index = 0; index < this.EnemyList.length; index++) {
            const ePos = this.EnemyList[index].getPosition();
            let dis = Vec3.squaredDistance(pPos,ePos)
            if (dis < minDis) {
                minDis = dis
                minIndex = index
            }
        }
        return this.EnemyList[minIndex]
    }

    OnPlayerHPChange(curHP: number, dmg: number, maxHP: number)
    {
        this.PlayerHP = curHP
        this.PlayerMaxHP = maxHP
    }

    OnGameStart()
    {
        this.ExpRoot = find("Canvas/ExpRoot")
        this.ChestRoot = find("Canvas/ChestRoot")
        this.EnemyRoot = find("Canvas/EnemyRoot")
        this.Player = find("Canvas/Player")
        this.Border = find("Canvas/Border")
        this.PlayerController = this.Player.getComponent(PlayerController)
        EventManager.instance.RegisterEvent(EventType.HPChange, this.OnPlayerHPChange, this)
    }

    OnLvUp()
    {
        this.AddProp(PlayerProp.MaxHP,1)
        this.AddProp(PlayerProp.MoveSpeed,0.1)
        this.AddProp(PlayerProp.Damega,0.1)
    }

    /*
    下一关，需要清空每关的缓存
    todo
    1.设置当前关卡最大值，防止单局游戏过长等balabala
    */
    NextLevel()
    {
        this.CurLevel ++
        this.IsGameStart = true
        this.ChestLootCount = 0
        this.EnemyList = new Array()
        this.ExpList = new Array()
        this.ChestList = new Array()
        EventManager.instance.DispatchEvent(EventType.ExpChange, this.ExpCount, this.LvUpExp, this.Lv)
        UIManager.instance.GetMainUI().SetTimer(GameManager.TURN_TIME + (this.CurLevel - 1) * 5)
    }

    // 游戏开始，无论是读档还是新开始都会进入的函数
    GameStart()
    {
        this.IsGameStart = true
        this.EnemyList = new Array()
        this.ExpList = new Array()
        this.ChestList = new Array()
        this.LvUpExp = (this.Lv + 1) * 5 // 设置一下升级的经验值
        EventManager.instance.DispatchEvent(EventType.ExpChange, this.ExpCount, this.LvUpExp, this.Lv)
        UIManager.instance.GetMainUI().SetTimer(GameManager.TURN_TIME + (this.CurLevel - 1) * 5)
    }

    //测试模式修改东西来这里
    GameDataInit()
    {
        this.ExpCount = 4// 经验值
        this.Lv = 0 // 等级
        this.LvUpExp = (this.Lv + 1) * 5// 升级所需经验值
        this.PlayerHP = 10
        this.PlayerMaxHP = 10
        this.CurLevel = 1 // 当前关卡
    }

    GameOver()
    {
        this.IsGameStart = false
    }

    //属性提升API
    AddProp(prop:PlayerProp,value:number)
    {
        switch (prop) {
            case PlayerProp.HP:
                this.PlayerController.AddHP(value)
                break;
            case PlayerProp.MaxHP:
                this.PlayerController.IncreaseHPMax(value)
                break
            case PlayerProp.MoveSpeed:
                JoyStick.PLAYER_MOVE_SPEED += value
                break
            case PlayerProp.Damega:
                Bullet.BULLET_DAMAGE += value
                break
            case PlayerProp.AttackInterval:
                this.PlayerController.AddAttackInterval(-0.1)
                break
            default:
                break;
        }
    }
}
